import { Component, Input, Output, EventEmitter, ViewChild, OnDestroy, OnInit, Injector } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
import { DepartService } from '../../../service/depart/depart.service';
import { NzTreeComponent, NzModalRef, NzMessageService, NzTreeNode, NzFormatEmitEvent, NzNotificationService } from 'ng-zorro-antd';
import { ModalHelper, _HttpClient } from '@delon/theme';
import { Subject, Observable } from 'rxjs';
import { MenuService } from '../../../service/menu/menu.service';
import { GroupService } from '../../../service/group/group.service';
import { SimpleTableComponent, SimpleTableColumn, SimpleTableData } from '@delon/abc';
import { BaseController } from '@shared/base-controller';
import { Constant } from '@core/constant';
declare var _: any;

@Component({
    selector: 'auth-select',    
    templateUrl: './auth-modal.component.html',
    styleUrls: ['./auth-modal.component.less']
})
export class AuthModalComponent extends BaseController implements OnInit {    
    menus: any;
    authMenus: any;
    defaultCheckList = [];
    @ViewChild('nzTree') nzTree: NzTreeComponent;
    private subject = new Subject();
    groupId;
    searchValue;
    
    authMenuBtn = true;
    elementBtn = true;
    elements = [];

    q: any = {
        menuId: '-1'
    };
    url = this.menuService.getElementMenu();
    data = [];
    @ViewChild('st') st: SimpleTableComponent;
    columns: SimpleTableColumn[] = [    
        { title: '', index: 'id', render: 'check'},          
        { title: '资源类型', index: 'type'},            
        { title: '资源名称', index: 'name' },
        { title: '资源地址', index: 'uri' },
        { title: '资源请求类型', index: 'method' }
    ];
    
    
    constructor(
        public injector: Injector,
        private modal: NzModalRef,        
        public msg: NzMessageService, 
        private modalSrv: ModalHelper,
        private menuService: MenuService,
        private groupService: GroupService,                
        private http: _HttpClient,
        private notification: NzNotificationService,
        private cnt: Constant
    ) {        
        super(injector);
    }

    ngOnInit() {       
        this.loadAllMenu();       
    }

    loadAllMenu() {
        // 获取当前账号可以权限下放的菜单
        this.groupService.getManageMenus().subscribe(data => {
            this.menus = [];
            let o = this.replaceKeysDeep(data, this.mapShortToLong);
            
            for (let index = 0; index < o.length; index++) {
                this.menus.push(
                    new NzTreeNode(o[index])
                );
            }      
            this.loadGroupMenus(this.groupId);
        });
    }

    /**
     * 获取角色关联的菜单
     */
    loadGroupMenus(groupId) {
        this.groupService.getAuthorityMenu(groupId).subscribe(data => {            
            this.defaultCheckList = data['data'].map(v => {
                return v.id
            })
        })
    }

    mapShortToLong: any = {
        "id": "key"        
    };

    replaceKeysDeep(obj, keysMap) { // keysMap = { oldKey1: newKey1, oldKey2: newKey2, etc...
        let that = this;
        return _.transform(obj, function(result, value, key) { // transform to a new object
      
          var currentKey = keysMap[key] || key; // if the key is in keysMap use the replacement, if not use the original key
      
          result[currentKey] = _.isObject(value) ? that.replaceKeysDeep(value, keysMap) : value; // if the key is an object run it through the inner function - replaceKeys
        });
    }

    close() {
        this.modal.close(true);
        this.modal.destroy();
    }

    mouseAction(name: string, e: NzFormatEmitEvent): void {   
        if (name === 'click') {                        
            if (e.node.isSelected) {                 
                // 获取角色对应的元素资源
                this.groupService.getAuthorityElement(this.groupId).subscribe(data => {
                    this.elements = data['data'];                    
                    this.q.menuId = e.node.key;
                    this.st.load(1, this.q);
                })                 
            } else {
                this.q.menuId = "-1";
                this.st.load(1, this.q);
            }
        }
    }

    save() {
        const list: NzTreeNode[] = this.nzTree.getCheckedNodeList();               
        this.subject.next(list);
        this.close();        
    }

    getSubject() {
        return this.subject;
    }

    selectChildren(data: NzTreeNode) {            
        let tree:NzTreeNode[] = this.nzTree.getCheckedNodeList();
        const ids = [];
        ids.push(data.key);
        for (let i = 0; i < tree.length; i++) {
            ids.push(tree[i].key);
        }
        this.getAllChildrenIds(ids, data);
        this.defaultCheckList = ids;
    }

    /**
     * 坑爹的ng-zorro 1.2.0版本有bug, 导致反选必须用该方式处理
     * lxm 2018年07月27日
     * @param data 
     */
    unSelectChildren(data: NzTreeNode) {     
        // 获取要删除的id   
        const ids = [];
        ids.push(data.key);        
        this.getAllChildrenIds(ids, data);     
        
        // 重新设置checkedlist
        let tmp = this.nzTree.getCheckedNodeList();        
        tmp = this.setCheckVal(tmp, ids);
        
        // 设置defaultlist
        data.isChecked = false;
        for (let i = 0; i < ids.length; i++) {
            let index = this.defaultCheckList.indexOf(ids[i]);
            if (index > -1) {
                this.defaultCheckList.splice(index, 1);
            }            
        }                        
    }

    setCheckVal(nodes: NzTreeNode[], ids: Array<any>) {
        
        let willDelId = [];
        for (let i = 0; i < nodes.length; i++) {        
            let index = ids.findIndex((v, ti) => {                  
                return v == nodes[i].key ? true : false;                                    
            })
            if (index > -1) {
                nodes[i].isChecked = false;
                willDelId.push(nodes[i].key);                        
            }            
        }
        for (let i = 0; i < willDelId.length; i++) {
            for (let j = 0; j < nodes.length; j++) {
                if (nodes[j].key === willDelId[i]) {
                    nodes.splice(j, 1);                        
                }
            }
        }
        return nodes;
    }

    getAllChildrenIds(ids, data: NzTreeNode) {
        if (data.children.length !== 0) {            
            for (let i = 0; i < data.children.length; i++) {
                ids.push(data.children[i].key);
                const child = data.children[i];
                this.getAllChildrenIds(ids, child);
            }
        }
        return;
    }

    selectOne(obj) {
        if (this.nzTree.getSelectedNodeList().length == 0) {
            this.msg.warning('请选择菜单');
            return false;
        }  
        if (obj.checked) {
            this.doAddElement(obj.id);
        } else {
            this.doRemoveElement(obj.id);            
        }
    }

    unSelectAll() {
        if (this.nzTree.getSelectedNodeList().length == 0) {
            this.msg.warning('请选择菜单');
            return;
        }     
        let list = this.st._data;
        for (let i = 0; i < list.length; i++) {            
            if (!list[i].checked) {
                continue;
            }
            list[i].checked = false;
            this.doRemoveElement(list[i].id);
        }     
    }

    selectAll() {
        if (this.nzTree.getSelectedNodeList().length == 0) {
            this.msg.warning('请选择菜单');
            return;
        }     
        let list = this.st._data;
        for (let i = 0; i < list.length; i++) {            
            if (list[i].checked) {
                continue;
            }
            list[i].checked = true;
            this.doAddElement(list[i].id);
        }        
    }

    doAddElement(elementId) {
        let node = this.nzTree.getSelectedNodeList()[0];
        this.groupService.addGroupElement(this.groupId, node.key, elementId).pipe(
            catchError(err => {
                return of(err);
            })
        ).subscribe(data => {
            if (data['status'] === 200) {
                this.createNotification('success', '成功', '资源权限添加成功');
            } else {
                this.createNotification('error', '失败', '资源权限添加失败');
            }
        })
    }

    doRemoveElement(elementId) {
        let node = this.nzTree.getSelectedNodeList()[0];
        this.groupService.removeGroupElement(this.groupId, node.key, elementId).pipe(
            catchError(err => {
                return of(err);
            })
        ).subscribe(data => {
            if (data['status'] === 200) {
                this.createNotification('success', '成功', '资源权限移除成功');
            } else {
                this.createNotification('error', '失败', '资源权限移除失败');
            }
        })
    }

    dataChange = (data: SimpleTableData[]) => {            
        return data.map((i: SimpleTableData, index: number) => {            
            let tmp = this.elements.findIndex((v, idx) => {
                return v === i.id
            })                    
            i.checked = tmp > -1; 
            return i;           
        });        
    }

    createNotification(type: string, title, msg): void {
        this.notification.create(type, title, msg);
    }

}